package com.bite.system.service.sysuser.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bite.common.core.constants.Constants;
import com.bite.common.core.domain.LoginUser;
import com.bite.common.core.domain.R;
import com.bite.common.core.domain.vo.LoginUserVO;
import com.bite.common.core.enums.ResultCode;
import com.bite.common.core.enums.UserIdentity;
import com.bite.common.core.utils.ThreadLocalUtil;
import com.bite.common.security.exception.ServiceException;
import com.bite.common.security.service.TokenService;
import com.bite.system.domain.system.SysUser;
import com.bite.system.domain.system.dto.SysUserAddDTO;
import com.bite.system.domain.system.dto.SysUserUpdateDTO;
import com.bite.system.domain.system.vo.SysUserVO;
import com.bite.system.mapper.sysuser.SysUserMapper;
import com.bite.system.service.sysuser.ISysUserService;
import com.bite.system.utils.BCryptUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

@RefreshScope
@Service
public class SysUserServiceImpl implements ISysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private TokenService tokenService;


    @Value("${jwt.secret}")
    private String secret;

    @Override
    public String login(String userAccount, String password) {
//        int i = 1/0;


        // select password from tb_sys_user where user_account = #{userAccount}
        LambdaQueryWrapper<SysUser> eq = new LambdaQueryWrapper<>(SysUser.class);
        SysUser sysUser = sysUserMapper.selectOne(eq
                .select(SysUser::getUserId, SysUser::getPassword, SysUser::getNickName)
                .eq(SysUser::getUserAccount, userAccount)
        );
//        R<Void> result = new R<>();
        if (sysUser == null) {
            // 未找到
//            return result.resultCode(ResultCode.FAILED_USER_NOT_EXISTS);
//            return R.fail(ResultCode.FAILED_USER_NOT_EXISTS);
            throw new ServiceException(ResultCode.FAILED_USER_NOT_EXISTS);
        }
        if (!BCryptUtils.matchesPassword(password, sysUser.getPassword())) {
            // 密码未配对
//            return result.resultCode(ResultCode.FAILED_LOGIN);
//            return R.fail(ResultCode.FAILED_LOGIN);
            throw new ServiceException(ResultCode.FAILED_LOGIN);
        }

        // 正确
//        return result.resultCode(ResultCode.SUCCESS);

        // 考虑到C端也需要类似的功能 所以就进行了封装
        LoginUser loginUser = new LoginUser(UserIdentity.ADMIN, sysUser.getNickName());

        return tokenService.createToken(sysUser.getUserId(), secret, loginUser);
    }


    @Override
    public boolean logout(String token) {
        return tokenService.delLoginUser(token, secret, UserIdentity.ADMIN);
    }

    @Override
    public int update(SysUserUpdateDTO userUpdateDTO) {
        SysUser sysUser = new SysUser();
        if (StrUtil.isNotEmpty(userUpdateDTO.getPassword())) {
            userUpdateDTO.setPassword(BCryptUtils.encryptPassword(userUpdateDTO.getPassword()));
        } else {
            userUpdateDTO.setPassword(null);
        }
        BeanUtil.copyProperties(userUpdateDTO, sysUser);
        return sysUserMapper.updateById(sysUser);
    }

    @Override
    public SysUserVO detail(Long userId) {
        if (userId == null) userId = ThreadLocalUtil.getUserId();
        SysUserVO sysUserVO = new SysUserVO();
        SysUser sysUser = sysUserMapper.selectOne(new LambdaQueryWrapper<>(SysUser.class)
                .eq(SysUser::getUserId, userId)
                .select(SysUser::getUserId, SysUser::getNickName)
                );
        BeanUtil.copyProperties(sysUser, sysUserVO);
        return sysUserVO;
    }

    @Override
    public int add(SysUserAddDTO sysUserSaveDTO) {
        // dto -> entity
        SysUser sysUser = SysUser.createByDTO(sysUserSaveDTO);

        try {
            ThreadLocalUtil.getUserId();
        } catch (Exception e) {
            ThreadLocalUtil.set(Constants.THREAD_LOCAL_USER_ID, Constants.SYSTEM_ID);
        }
        return sysUserMapper.insert(sysUser);
    }

    @Override
    public LoginUserVO info(String token) {
        LoginUserVO loginUserVO = tokenService.getLoginUserVO(token, secret);
        if (loginUserVO == null) {
            throw new ServiceException(ResultCode.FAILED);
        }
        return loginUserVO;
    }

}
